﻿using System;
using System.Collections.Generic;
using Outlook = Microsoft.Office.Interop.Outlook;

namespace WLWCreateCalendarItemPlugin
{
    public static class OutlookUtility
    {
        /// <summary>
        /// Connect to Microsoft Outlook
        /// </summary>
        /// <returns></returns>
        private static Outlook.NameSpace ConnectToOutlook()
        {
            Outlook._Application olApp = new Outlook.Application();

            var mapiNs = olApp.GetNamespace("MAPI");

            mapiNs.Logon(string.Empty, null, null, null);

            return mapiNs;
        }

        /// <summary>
        /// Create a calendar appointment on a specified calendar within Outlook
        /// </summary>
        /// <param name="calendarFolderName"></param>
        /// <param name="articleTitle"></param>
        /// <param name="blogName"></param>
        /// <param name="datePublished"></param>
        public static void CreateOutlookAppointment(string calendarFolderName, string articleTitle, string blogName, DateTime datePublished)
        {
            var mapiNs = ConnectToOutlook();
            var calendarFolder = GetFolderFromPath(calendarFolderName, mapiNs.Folders);

            Outlook._Items oItems = calendarFolder.Items;

            //
            // Search for our appointment and if it doesn't exist,
            // create a new one.  Otheriwse, just reuse the old one.
            //
            var newAppointment = (Outlook._AppointmentItem)oItems.Find(string.Format("[Subject] = '{0}'", articleTitle)) ??
                                 (Outlook._AppointmentItem)oItems.Add("IPM.Appointment");

            newAppointment.Subject = articleTitle;
            newAppointment.Body = string.Empty;
            newAppointment.Start = datePublished;
            newAppointment.BusyStatus = Outlook.OlBusyStatus.olFree;
            newAppointment.AllDayEvent = true;
            newAppointment.Categories = blogName;
            newAppointment.ReminderMinutesBeforeStart = 0;
            newAppointment.ReminderSet = false;
            newAppointment.Save();
        }

        /// <summary>
        /// Create a collection of Calendars found in Outlook
        /// </summary>
        /// <returns></returns>
        public static MapiFolderCollection LoadCalendarFolders()
        {
            var mapiFolderCollection = new MapiFolderCollection();

            var mapiNs = ConnectToOutlook();
            var rootFolderList = mapiNs.Folders;

            var folderList = new List<Outlook.MAPIFolder>();

            foreach (Outlook.MAPIFolder mainFolder in rootFolderList)
            {
                folderList = GetFolderList(mainFolder, folderList);
            }

            for (var index = 0; index < folderList.Count; index++)
            {
                if (folderList[index].DefaultItemType != Outlook.OlItemType.olAppointmentItem)
                {
                    continue;
                }

                var parentFolderName = ((Outlook.MAPIFolder)folderList[index].Parent).Name;
                var folderName = folderList[index].Name;

                mapiFolderCollection.Add(new MapiFolder() { DisplayName = string.Format("{0} ({1})", folderName, parentFolderName), FullPath = folderList[index].FullFolderPath });
            }

            return mapiFolderCollection;
        }

        /// <summary>
        /// Retrieve the handle to an Outlook folder given a full path
        /// </summary>
        /// <param name="folderPath"></param>
        /// <param name="folders"></param>
        /// <returns></returns>
        private static Outlook.MAPIFolder GetFolderFromPath(string folderPath, Outlook.Folders folders)
        {
            var folderName = folderPath.Substring(0, folderPath.Substring(4).IndexOf("\\", StringComparison.Ordinal) + 4);

            try
            {
                foreach (Outlook.MAPIFolder mapiFolder in folders)
                {
                    if (!(mapiFolder.FullFolderPath.StartsWith(folderName)))
                    {
                        continue;
                    }

                    if (mapiFolder.FullFolderPath == folderPath)
                    {
                        return mapiFolder;
                    }

                    var folderFromPath = GetFolderFromPath(folderPath, mapiFolder.Folders);

                    if (folderFromPath != null)
                    {   
                        return folderFromPath;
                    }
                }

                return null;
            }
            catch 
            { 
                return null; 
            }
        }

        /// <summary>
        /// Returns a list of all the folder inside given folder.
        /// </summary>
        /// <param name="folder">Input Folder</param>
        /// <param name="folderList">List of Folders</param>
        /// <returns></returns>
        private static List<Outlook.MAPIFolder> GetFolderList(Outlook.MAPIFolder folder, List<Outlook.MAPIFolder> folderList)
        {
            if (folder == null || 
                folderList == null)
            {
                return folderList;
            }

            folderList.Add(folder);

            for (var index = 1; index <= folder.Folders.Count; index++)
            {
                GetFolderList(folder.Folders[index], folderList);
            }

            return folderList;
        }
    }
}
